//! 泛型（Generics）
//!
//! 泛型是 Rust 中一个强大的特性，允许我们编写适用于多种类型的代码。
//! 使用泛型可以避免代码重复，提高代码的复用性和类型安全性。

use std::fmt::{Debug, Display};

/// 1. 泛型函数
///
/// 泛型函数可以处理多种类型的数据，而不需要为每种类型都编写单独的函数。
/// 一个简单的泛型函数，用于交换元组中的两个元素
fn swap<T>(pair: (T, T)) -> (T, T) {
    let (a, b) = pair;
    (b, a)
}

/// 泛型函数，返回切片中的最大值
/// 需要指定 T 实现了 PartialOrd trait，这样才可以比较大小
fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];

    for item in list.iter() {
        if item > largest {
            largest = item;
        }
    }

    largest
}

/// 2. 泛型结构体
///
/// 结构体也可以使用泛型参数，使其能够存储不同类型的值。
/// 一个存储单个值的泛型结构体（具名字段结构体）
#[derive(Debug)]
struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    /// 创建一个新的 Point 实例
    fn new(x: T, y: T) -> Point<T> {
        Point { x, y }
    }
}

/// 为特定类型实现方法
impl Point<f64> {
    /// 只有当 T 是 f64 时，才计算点到原点的距离
    fn distance_from_origin(&self) -> f64 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

/// 混合类型的 Point 结构体（具名字段结构体）
#[derive(Debug)]
struct MixedPoint<T, U> {
    x: T,
    y: U,
}

impl<T, U> MixedPoint<T, U> {
    fn new(x: T, y: U) -> MixedPoint<T, U> {
        MixedPoint { x, y }
    }

    /// 方法使用不同的泛型参数 V, W
    fn mixup<V, W>(self, other: MixedPoint<V, W>) -> MixedPoint<T, W> {
        MixedPoint { x: self.x, y: other.y }
    }
}

/// 3. 泛型枚举
///
/// 标准库中的 Option 和 Result 都是泛型枚举的典型例子
/// 简化版的 Option 枚举
#[derive(Debug)]
enum MyOption<T> {
    Some(T),
    None,
}

/// 简化版的 Result 枚举
#[derive(Debug)]
enum MyResult<T, E> {
    Ok(T),
    Err(E),
}

/// 4. 泛型 trait 和实现
///
/// trait 也可以是泛型的
/// 定义一个泛型 trait
trait Summary {
    fn summarize(&self) -> String;
}

/// 为 i32 实现 Summary trait
impl Summary for i32 {
    fn summarize(&self) -> String {
        format!("数字: {}", self)
    }
}

/// 为 String 实现 Summary trait
impl Summary for String {
    fn summarize(&self) -> String {
        format!("字符串: {}", self)
    }
}

/// 泛型 trait 实现示例
trait MyClone<T> {
    fn my_clone(&self) -> T;
}

impl<T: Clone> MyClone<T> for T {
    fn my_clone(&self) -> T {
        self.clone()
    }
}

/// 5. trait bounds（trait 边界）
///
/// 通过 trait bounds 可以指定泛型类型必须实现的 trait
/// 使用 where 子句的泛型函数
fn some_function<T, U>(t: T, u: U) -> i32
where
    T: Display + Clone,
    U: Clone + Debug,
{
    1
}

/// 打印两个实现了 Display trait 的值
fn print_both<T: Display, U: Display>(a: T, b: U) {
    println!("{} 和 {}", a, b);
}

/// 6. 关联类型
///
/// trait 中的关联类型提供了一种在 trait 中定义占位符类型的方式
/// 定义一个带有关联类型的 trait
trait Container {
    type Item;

    fn insert(&mut self, item: Self::Item);
    fn remove(&mut self) -> Self::Item;
    fn is_empty(&self) -> bool;
}

/// 为自定义容器实现 trait
struct MyContainer<T> {
    items: Vec<T>,
}

impl<T> MyContainer<T> {
    fn new() -> MyContainer<T> {
        MyContainer { items: Vec::new() }
    }
}

impl<T> Container for MyContainer<T> {
    type Item = T;

    fn insert(&mut self, item: Self::Item) {
        self.items.push(item);
    }

    fn remove(&mut self) -> Self::Item {
        self.items.pop().expect("Container is empty")
    }

    fn is_empty(&self) -> bool {
        self.items.is_empty()
    }
}

/// 主演示函数
pub fn demonstrate_generics() {
    println!("=== 泛型（Generics）示例 ===");

    // 泛型函数示例
    let pair = (1, 2);
    let swapped = swap(pair);
    println!("交换元组 {pair:?} -> {swapped:?}");

    let numbers = vec![34, 50, 25, 100, 65];
    let largest_number = largest(&numbers);
    println!("列表 {numbers:?} 中的最大值是: {largest_number}");

    // 泛型结构体示例
    let integer_point = Point::new(1, 2);
    println!("整数点: {integer_point:?}");

    let float_point = Point::new(1.0, 2.0);
    println!("浮点数点: {float_point:?}");

    let distance: f64 = float_point.distance_from_origin();
    println!("点到原点的距离: {distance:.2}");

    // 混合类型点
    let mixed_point = MixedPoint::new(5, 4.0);
    let another_point = MixedPoint::new("Hello", 'w');
    let mixed_result = mixed_point.mixup(another_point);
    println!("混合点: {mixed_result:?}");

    // 泛型枚举示例
    let some_number = MyOption::Some(5);
    let no_number: MyOption<i32> = MyOption::None;
    println!("Some 值: {some_number:?}");
    println!("None 值: {no_number:?}");

    let success = MyResult::Ok::<i32, String>(42);
    let error = MyResult::Err::<i32, String>("出错了".to_string());
    println!("成功结果: {success:?}");
    println!("错误结果: {error:?}");

    // trait 示例
    let number = 42;
    let text = String::from("你好，Rust");
    println!("{}", number.summarize());
    println!("{}", text.summarize());

    // 关联类型示例
    let mut container = MyContainer::new();
    container.insert(1);
    container.insert(2);
    container.insert(3);
    println!("容器是否为空: {}", container.is_empty());
    let item = container.remove();
    println!("移除的元素: {item}");
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_swap() {
        let original = (1, 2);
        let swapped = swap(original);
        assert_eq!(swapped, (2, 1));
    }

    #[test]
    fn test_largest() {
        let numbers = vec![1, 5, 3, 9, 2];
        let largest_number = largest(&numbers);
        assert_eq!(*largest_number, 9);
    }

    #[test]
    fn test_point() {
        let point = Point::new(1, 2);
        assert_eq!(point.x, 1);
        assert_eq!(point.y, 2);
    }

    #[test]
    fn test_mixed_point() {
        let point1 = MixedPoint::new(1, 2.0);
        let point2 = MixedPoint::new("Hello", 'W');
        let result = point1.mixup(point2);
        assert_eq!(result.x, 1);
        assert_eq!(result.y, 'W');
    }

    #[test]
    fn test_my_option() {
        let some_value = MyOption::Some(5);
        match some_value {
            MyOption::Some(value) => assert_eq!(value, 5),
            MyOption::None => panic!("不应该为 None"),
        }
    }
}
